package com.sprouting.personal.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.personal.annotations.ApiIdempotent;
import com.sprouting.personal.interfaces.common.Constant;
import com.sprouting.personal.interfaces.common.ConstantPath;
import com.sprouting.personal.model.common.ResultJson;
import com.sprouting.personal.model.common.jsr.AddGroup;
import com.sprouting.personal.model.common.jsr.UpdGroup;
import com.sprouting.personal.model.entity.Config;
import com.sprouting.personal.model.entity.Dict;
import com.sprouting.personal.model.entity.Movies;
import com.sprouting.personal.service.ConfigService;
import com.sprouting.personal.service.DictService;
import com.sprouting.personal.service.PsMoviesService;
import com.sprouting.personal.utils.CheckTool;
import com.sprouting.personal.utils.EntityTool;
import com.sprouting.personal.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * 影视
 *
 * @author longx
 * @since 2022-12-16 13:33:23
 */
@Slf4j
@RestController
@RequestMapping("/movies")
public class PsMoviesController {

    @Autowired
    private PsMoviesService psMoviesService;
    @Autowired
    private DictService dictService;
    @Autowired
    private ConfigService configService;

    /**
     * 文件存储基础路径
     */
    @Value("${upload.data.base.path}")
    private String basePath;
    /**
     * 上传图片类型
     */
    @Value("#{'${upload.image.type}'.split(',')}")
    private List<String> uploadImageTypeList;
    /**
     * 图片文件上传最大长度
     */
    @Value("${upload.image.max.length}")
    private Integer uploadImageMaxLength;


    /**
     * 根据主键查询影视信息
     * @param id 主键
     * @return
     */
    @PostMapping("/getMoviesById")
    public ResultJson getMoviesById(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorIllegal();
        }
        return ResultJson.success(psMoviesService.getPsMoviesById(id));
    }

    /**
     * 分页查询影视信息
     * @param page 分页参数
     * @param movies 查询参数
     * @return
     */
    @PostMapping("/getMoviesPage")
    public ResultJson getMoviesPage(Page page, Movies movies){
        if (movies == null){
            movies = new Movies();
        }
        movies.setUserId(StpUtil.getLoginIdAsString());

        return ResultJson.success(psMoviesService.getMoviesPage(page, movies));
    }

    /**
     * 物理删除影视
     * @param id 主键
     * @return
     */
    @PostMapping("/delMovies")
    public ResultJson delMovies(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorIllegal();
        }
        Movies movies = psMoviesService.getPsMoviesById(id);
        if (movies == null){
            return ResultJson.errorPram();
        }

        psMoviesService.removeById(id);

        String icoPath = movies.getIcoPath();
        if (!CheckTool.checkNull(icoPath)){
            // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
            if (FileUtil.isFile(basePath + icoPath)){
                FileUtil.del(basePath + icoPath);
            } else {
                log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
            }
        }

        return ResultJson.success();
    }

    /**
     * 保存影视信息
     * @param movies 影视信息
     * @param file 上传的影剧海报图片
     * @return
     */
    @PostMapping("/saveMovies")
    @ApiIdempotent
    public ResultJson<Movies> saveMovies(@Validated(AddGroup.class) Movies movies, @RequestParam(value = "file", required = false) MultipartFile file){
        if (CheckTool.checkNull(basePath)){
            return ResultJson.error("图片存储路径未初始化，请补充application.properties配置信息");
        }
        String msg = checkMovies(movies);
        if (msg != null){
            return ResultJson.error(msg);
        }

        // 上传封面
        if (file != null){
            String err = saveMoviesCover(file, movies);
            if (err != null){
                return ResultJson.error(err);
            }
        }

        // 补充部分数据
        if (movies.getContinueSee() == null){
            movies.setContinueSee(Constant.YesOrNo.NO);
        }
        if (movies.getGrade() == null){
            movies.setGrade(3);
        }

        movies.setId(IdTool.getId());
        movies.setUserId(StpUtil.getLoginIdAsString());
        EntityTool.buildSaveBase(movies, StpUtil.getLoginIdAsString());
        psMoviesService.save(movies);
        return ResultJson.success(movies);
    }

    /**
     * 更新影视信息
     * @param movies 影视
     * @param file 封面文件
     * @return
     */
    @PostMapping("/updMovies")
    @ApiIdempotent
    public ResultJson<Movies> updMovies(@Validated(UpdGroup.class) Movies movies, @RequestParam(value = "file", required = false) MultipartFile file){
        String msg = checkMovies(movies);
        if (msg != null){
            return ResultJson.error(msg);
        }
        // 先找到旧的影视信息，防止数据被覆盖
        Movies moviesDb = psMoviesService.getPsMoviesById(movies.getId());
        if (moviesDb == null){
            return ResultJson.errorPram();
        }

        // 上传封面
        if (file != null){
            String err = saveMoviesCover(file, movies);
            if (err != null){
                return ResultJson.error(err);
            }
        }

        EntityTool.buildUpdBase(movies, StpUtil.getLoginIdAsString());
        psMoviesService.updateById(movies);

        // 清理原始数据
        clearOldData(file, moviesDb);
        return ResultJson.success(movies);
    }

    /**
     * 获取影视类型
     * @return
     */
    @GetMapping("/getMoviesType")
    public ResultJson getMoviesType(){
        List<Dict> dictList = dictService.getType(Constant.RetainDictGroup.MOVIES_GROUP, StpUtil.getLoginIdAsString());
        return ResultJson.success(dictList);
    }

    /**
     * 获取默认的观影地址
     * @return
     */
    @GetMapping("/getMoviesLocale")
    public ResultJson<Config> getMoviesLocale(){
        Config config = configService.getConfigByCodeAutomaticCompletion(Constant.ConfigCode.VIEWING_ADDRESS, StpUtil.getLoginIdAsString());
        return ResultJson.success(config);
    }

    /**
     * 清理旧的封面文件
     * @param file 上传的图片文件
     * @param movies 影视信息
     */
    private void clearOldData(MultipartFile file, Movies movies){
        // 只有新增之后才能删除旧的，否则不去操作
        if (file != null){
            String icoPath = movies.getIcoPath();
            if (!CheckTool.checkNull(icoPath)){
                // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
                if (FileUtil.isFile(basePath + icoPath)){
                    FileUtil.del(basePath + icoPath);
                } else {
                    log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
                }
            }
        }
    }

    /**
     * 保存影视封面
     * @param file 封面文件
     * @param movies 影视信息
     * @return 非null返回，则是有错误信息
     */
    private String saveMoviesCover(MultipartFile file, Movies movies){
        String originalFilename = file.getOriginalFilename();
        if (CheckTool.checkNull(originalFilename)){
            return "获取文件名失败";
        }
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        if (CheckTool.checkNull(suffix)){
            // 检查特殊情况下的文件名不符合
            return "非法上传图片名，不支持的后缀";
        }
        if (uploadImageTypeList != null){
            if (!uploadImageTypeList.contains(suffix)){
                return "上传图片类型不支持";
            }
        }
        if (file.getSize() > uploadImageMaxLength){
            return "上传图片超过限定大小";
        }

        String path = String.format(ConstantPath.Path.MOVIES_ICO, basePath, StpUtil.getLoginIdAsString(), IdTool.getId(), suffix);
        File toFile = new File(path);
        // 上传路径
        if (!FileUtil.exist(toFile)){
            FileUtil.touch(toFile);
        }

        try {
            file.transferTo(toFile);
        } catch (IOException e) {
            log.error("图片上传失败", e);
            return "图片上传失败";
        }

        // 只保存相对路径
        String replacePath = path.replace(basePath, "");
        movies.setIcoPath(replacePath);
        return null;
    }

    /**
     * 校验影视
     * @param movies 影视信息
     * @return 非null则是错误信息
     */
    private String checkMovies(Movies movies){
        Movies db = psMoviesService.getPsMoviesByName(movies.getId(), StpUtil.getLoginIdAsString(), movies.getName(), movies.getDirector());
        if (db != null){
            return "该影视作品已入库，不需要重复录入";
        }

        return null;
    }
}

